import EventEmitter from "events"
import TypedEmitter from "typed-emitter"
export interface WsMessage{
  /**
   * 类型
   */
  type:string
  /**
   * 内容
   */
  content:string
}
export type MessageEvents = {
  /**
   * 连接建立时
   */
  onOpen():any
  /**
   * 断连后重新连接
   */
  onReConnect():any
  /**
   * 收到消息时
   * @param msg
   */
  onMessage(msg:WsMessage):any
  /**
   * 验证身份完成时
   */
  onAuthenticated():any
  /**
   * 关闭时
   */
  onClose():any

}


const messageEmitter = new EventEmitter() as TypedEmitter<MessageEvents>


const state = {
  ws:<WebSocket | null>null,
  connecting:false,
  enableLog: true
}

function wsLog(content:string){
    if(state.enableLog){
      console.log("[WebSocket] " + content)
    }
}

let host = ""
if(import.meta.env.DEV){
  host = import.meta.env.VITE_WEB_SOCKET as string
}else{
  
  host = window.location.host + '/api/client/ws'
  if(window.location.href.startsWith("https")){
    host = "wss://" + host
  }else{
    host = "ws://" + host
  }
}
 


/**
 * 防抖
 * @param fn 
 * @param delay 
 * @returns 
 */
function debounce(fn:Function,delay:number){
  let timer:any = null //借助闭包
  return function() {
      if(timer){
          clearTimeout(timer) 
          timer = setTimeout(fn,delay) 
      }else{
          timer = setTimeout(fn,delay)
      }
  }
}

/**
 * 防抖5秒等待 重连
 */
const reConnect = debounce(()=>{
  initWebsocket(true);
},5000);



function initWebsocket(isReconnect:boolean = false){
  
  let token=localStorage.getItem('jst:token')?.substring(7);
  let inhost=host+'?access_token='+token
  // wsLog('Try Connect WebSocket Server: ' + inhost)
  state.ws = null
  state.ws = new WebSocket(inhost as string);
  state.ws.onopen = ()=>{
    wsLog('Connected!')
    state.connecting = true

    messageEmitter.emit("onOpen")
    if(isReconnect){
      messageEmitter.emit("onReConnect")
    }
  }
  state.ws.onmessage=(msg)=>{
    wsLog(msg.toString())
    // console.log(msg)
    let content = msg.data.toString("utf-8")
    let message:WsMessage = JSON.parse(content)
    if(message.type == "pong"){
      return
    }
    messageEmitter.emit("onMessage",message)
  }
  state.ws.onclose=(err)=>{
    wsLog('Close!')
    // console.log(err)
    state.connecting = false
    reConnect();
  }
  state.ws.onerror,()=>{
    wsLog('Error!')
    state.connecting = false
    reConnect();
  }
}

function send(msg:WsMessage){
  if(state.ws == null || state.connecting == false){
    return
  }
  
  state.ws.send(JSON.stringify(msg))
}

// 20秒进行一次heart beat
const heartBeat = setInterval(()=>{
  if(state.ws == null || state.connecting == false){
    return
  }
  state.ws.send("{type:'ping'}")
},5000); 

initWebsocket();



export default {
  event:messageEmitter,
  send
}
